/*
 * @(#)RespondingQueryService.java
 * Date 2013-10-20
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.xca.service;

import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import javax.inject.Inject;

import javax.xml.bind.JAXBElement;

import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryRequest;
import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryResponse;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.AdhocQueryType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.IdentifiableType;
import oasis.names.tc.ebxml_regrep.xsd.rim._3.RegistryObjectListType;

import org.apache.commons.lang3.StringUtils;

import us.hornerscorners.lamppost.atna.client.utils.AtnaUtils;

import us.hornerscorners.lamppost.exception.ServiceActionError;
import us.hornerscorners.lamppost.exception.SeverityType;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;

import us.hornerscorners.lamppost.model.audit.AuditContext;
import us.hornerscorners.lamppost.model.audit.CodedValueType;

import us.hornerscorners.lamppost.registry.client.RegistryClient;

import us.hornerscorners.lamppost.registry.constant.ErrorCode;
import us.hornerscorners.lamppost.registry.constant.ResponseStatus;

import us.hornerscorners.lamppost.registry.service.AtnaRegistryService;
import us.hornerscorners.lamppost.registry.service.IStoredQueryService;
import us.hornerscorners.lamppost.registry.service.SimpleXDSParser;

import us.hornerscorners.lamppost.registry.transformer.xds
    .RegistryResponseTypeTransformer;

import us.hornerscorners.lamppost.repository.inject.RepositoryTarget;

import us.hornerscorners.lamppost.xca.inject.GatewayTarget;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-10-20
 * @author         Jim Horner
 */
@ApplicationScoped
public class RespondingQueryService implements IStoredQueryService {

    /** Field description */
    @Inject
    private AtnaRegistryService atnaService;

    /** Field description */
    @Inject
    private IHEConfig config;

    /** Field description */
    @Inject
    @GatewayTarget
    private RegistryClient registryClient;

    /** Field description */
    @Inject
    @RepositoryTarget
    private RegistryResponseTypeTransformer responseTypeTransformer;

    /** Field description */
    @Inject
    private SimpleXDSParser xdsParser;

    /**
     * Constructs ...
     *
     */
    public RespondingQueryService() {

        super();
    }

    /**
     * Method description
     *
     *
     * @param body
     *
     * @return
     */
    @Override
    public AdhocQueryResponse executeStoredQuery(AuditContext auditContext,
            AdhocQueryRequest body) {

        AdhocQueryResponse result = null;

        try {

            ServiceActionError error = isValidHome(body.getAdhocQuery());

            if (error != null) {

                result = new AdhocQueryResponse();
                result.setRegistryObjectList(new RegistryObjectListType());
                result.setStatus(ResponseStatus.Failure.getCode());
                result.setRegistryErrorList(
                    this.responseTypeTransformer.createRegistryErrorList(
                        getClass(), error));

            } else {

                CodedValueType eventType = AtnaUtils.createCodedValue("ITI-18",
                                               "IHE Transactions",
                                               "Registry Stored Query");

                AuditContext queryContext = new AuditContext(eventType,
                                                this.config.getClientConfig(),
                                                auditContext.getTransactionContext(),
                                                auditContext.getAddressContext());

                result = this.registryClient.executeStoredQuery(queryContext, body);

                // make sure home is set
                String home = this.config.getHomeCommunityId();

                List<JAXBElement<? extends IdentifiableType>> idtypes =
                    result.getRegistryObjectList().getIdentifiable();

                for (JAXBElement<? extends IdentifiableType> idtype : idtypes) {

                    idtype.getValue().setHome(home);
                }
            }

        } finally {

            this.atnaService.sendQueryReceivedAuditMessage(auditContext, body, result);
        }

        return result;
    }

    /**
     * Method description
     *
     *
     *
     * @return
     */
    private ServiceActionError isValidHome(AdhocQueryType query) {

        ServiceActionError result = null;

        String home = query.getHome();

        if (StringUtils.isBlank(home)) {

            if (StringUtils.isBlank(this.xdsParser.parsePatientCX(query))) {

                String msg =
                    "AdhocQuery does not contain a patientId slot and is missing homeCommunityId.";

                result =
                    new ServiceActionError(ErrorCode.XDSMissingHomeCommunityId.getCode(),
                                           msg, SeverityType.Error);
            }

        } else {

            String homeCommunityId = this.config.getHomeCommunityId();

            if (homeCommunityId.equals(home) == false) {

                String msg =
                    String.format(
                        "[%s] in AdhocQuery is not a recognized homeCommunityId.", home);

                result = new ServiceActionError(ErrorCode.XDSUnknownCommunity.getCode(),
                                                msg, SeverityType.Error);

            }
        }

        return result;
    }
}
